package com.lalilu.lmedia.extension

import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.debounce
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch

fun interface Pipe<I : Any, O : Any> {
    fun flow(upStream: I): Flow<O>
}

class Slot<I : Any, O : Any> constructor(defaultValue: Pipe<I, O>) {
    internal val flow = MutableStateFlow(defaultValue)

    fun setPipe(pipe: Pipe<I, O>) {
        flow.value = pipe
    }
}

@OptIn(ExperimentalCoroutinesApi::class)
fun <I : Any, O : Any> Flow<I>.connect(slot: Slot<I, O>): Flow<O> =
    flatMapLatest { value -> slot.flow.flatMapLatest { it.flow(value) } }


/**
 * 简易的防抖实现
 */
@OptIn(FlowPreview::class)
fun CoroutineScope.debounce(delay: Long, callback: suspend () -> Unit): () -> Unit {
    val countFlow = MutableStateFlow(System.currentTimeMillis())

    countFlow.debounce(delay)
        .onEach { callback() }
        .launchIn(this)

    return { launch { countFlow.emit(System.currentTimeMillis()) } }
}